package io.github.weiranyi.studyjedis;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisPoolUtil {
    private JedisPoolUtil(){}
    private volatile static JedisPool jedisPool = null;
    private volatile static Jedis jedis = null;

    // 返回一个连接池
    private static JedisPool getInstance(){
        // 双层检测锁机制[企业常用]  商场->体温正常+健康码绿码->放行
        /*
            - 第一次校验：由于单例模式只需要创建一次实例，如果后面再次调用getInstance方法，
              则直接返回之前创建的实例，因此大部分时间不需要执行同步方法里面的代码，大大提高了性能。
              如果不加第一次校验的话，那跟懒汉模式没什么区别，每次都要去竞争锁
            - 第二次校验：若没有第二次校验，假设线程t1执行了第一次校验后，判断为null，这时t2也获取了
              CPU执行权，也执行第一次校验判断也为null。接下来t2获得锁，创建实例。这时t1又获得CPU执行
              权，由于之前已经进行了第一次校验，获得锁后，直接创建实例。结果就会导致创建多个实例。
              所以需要在同步代码里面进行第二次校验，如果实例为空，则进行创建。
         */
        if (jedisPool == null){ //测温
            synchronized (JedisPool.class){ //排队进站
                if (jedisPool == null){ //查看健康码
                    JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
                    jedisPoolConfig.setMaxTotal(1000);
                    jedisPoolConfig.setMaxIdle(30);
                    jedisPoolConfig.setMaxWaitMillis(60*1000); //毫秒
                    jedisPoolConfig.setTestOnBorrow(true); // 后台运行
                    jedisPool = new JedisPool(jedisPoolConfig,"192.168.182.129",6379);
                }
            }
        }
        return jedisPool;
    }
    // 返回一个Jedis对象
    public static Jedis getJedis(){
        if (jedis == null){
            jedis = getInstance().getResource();
        }
        return jedis;
    }

}
